package api

import (
	"encoding/hex"
	"fmt"
	"github.com/gorilla/websocket"
	"net/http"
	"openzbox.com/driver/conn/serial"
	"openzbox.com/frame/echo"
	"openzbox.com/gateway/core"
	"openzbox.com/log"
	"openzbox.com/utils"
	"sync"
)

type wsData struct {
	Name string
	Data string
	Type uint8
}

var (
	upgrader = websocket.Upgrader{
		//ReadBufferSize:   1024,
		//WriteBufferSize:  1024,
		CheckOrigin: checkOrigin,
		//HandshakeTimeout: 5 * time.Second,
	}
	ClientWS map[string]*websocket.Conn = make(map[string]*websocket.Conn)
)

//允许websocket跨域
func checkOrigin(r *http.Request) bool {
	return true
}
func WebSocketService(c echo.Context) error {

	fmt.Println("open WebSocketService", c.QueryParam("id"))

	portname := c.QueryParam("id")
	var err error
	ws, err := upgrader.Upgrade(c.Response(), c.Request(), nil)
	if err != nil {
		return err
	}
	//defer ws.Close()
	var wsData = wsData{}
	//ws.SetCloseHandler(clientCloseHandler)
	ws.SetCloseHandler(func(code int, text string) error {
		//deleteClient(id)
		//log.Info(code)
		//释放websocket
		/*conn := ClientWS[c.QueryParam("id")]
		if conn != nil {
			conn.Close()
			delete(ClientWS, portid)
		}*/
		delete(ClientWS, portname)
		return nil
	})
	//创建的连接放入map
	ClientWS[portname] = ws
	for {
		//time.Sleep(time.Second * 1)
		err := ws.ReadJSON(&wsData) //ws.ReadMessage()
		if err != nil {
			if websocket.IsUnexpectedCloseError(err, websocket.CloseGoingAway) {
				log.Errorf("IsUnexpectedCloseError: %v", err)
			}
			break
		}
		//fmt.Println("WebSocketService...")
		port, err := core.Mybox.GetPort(wsData.Name)
		if err != nil {
			log.Errorf("get port error:%s", wsData.Name)
			continue
		}
		if wsData.Type == 1 {
			data, err := hex.DecodeString(wsData.Data)
			if err != nil {
				// handle error
			}
			//log.Infof("hex.DecodeString %v", data)
			err = port.SendBytes(data)
			if err != nil {
				log.Errorf("write port error:%s %s", wsData.Name, err.Error())
				continue
			}
		} else {
			err = port.SendString(wsData.Data)
			if err != nil {
				log.Errorf("write port error:%s %s", wsData.Name, err.Error())
				continue
			}
		}
		log.Infof("receive webSocket message:%v", wsData)
	}
	return nil
}

func OpenPort(c echo.Context) error {
	//portName := c.FormValue("name")

	/*baudstr := c.FormValue("baud")
	databitstr := c.FormValue("databits")
	stopbitstr := c.FormValue("stopbits")
	paritystr := c.FormValue("parity")

	databits, err := strconv.ParseInt(databitstr, 10, 32)
	stopbits, err := strconv.ParseInt(stopbitstr, 10, 32)
	baud, err := strconv.ParseInt(baudstr, 10, 32)

	if err != nil {
		info = utils.Response{Code: 0, Desc: "端口参数错误。"}
	}*/
	info := utils.ResponseSuccess("")
	var conf serial.Config
	err := c.Bind(&conf)
	if err != nil {
		info.Code = 1
		info.Desc = "端口参数配置错误：" + err.Error()
		//return c.String(http.StatusBadRequest, err.Error())
		return c.JSON(http.StatusOK, info)
	}
	port, err := core.Mybox.GetPort(conf.PortName)
	if err != nil {
		info = utils.ResponseError("获取端口错误。")
	}
	err = port.OpenWithOpts(uartByteReceived, conf)

	if err != nil {
		info = utils.ResponseError("打开端口出错。" + err.Error())
	}
	return c.JSON(http.StatusOK, info)
}

func ClosePort(c echo.Context) error {
	portName := c.FormValue("portName")
	info := utils.ResponseSuccess("")
	//获取端口
	port, err := core.Mybox.GetPort(portName)
	if err != nil {
		return c.JSON(http.StatusOK, utils.ResponseError("获取端口出错."))
	}
	//关闭端口
	err = port.Close()
	if err != nil {
		return c.JSON(http.StatusOK, utils.ResponseError("关闭端口出错."))
	}
	return c.JSON(http.StatusOK, info)
}

func ListPorts(c echo.Context) error {
	return c.JSON(http.StatusOK, core.Mybox.ListPorts())
}

func GetPort(c echo.Context) error {
	name := c.Param("name")
	port, err := core.Mybox.GetPort(name)
	if err != nil {
		return c.JSON(http.StatusOK, utils.ResponseError("不存在的端口."))
	}
	return c.JSON(http.StatusOK, port)
}

func UpdatePort(c echo.Context) error {
	name := c.Param("name")
	info := utils.ResponseSuccess("")

	var conf serial.Config
	err := c.Bind(&conf)
	if err != nil {
		info.Code = 1
		info.Desc = "端口参数配置错误：" + err.Error()
		//return c.String(http.StatusBadRequest, err.Error())
		return c.JSON(http.StatusOK, info)
	}

	port, err := core.Mybox.GetPort(name)
	if err != nil {
		return c.JSON(http.StatusOK, utils.ResponseError("不存在的端口."))
	}

	port.SetOpts(conf)

	nport, err := core.Mybox.UpdatePort(port)
	if err != nil {
		return c.JSON(http.StatusOK, utils.ResponseError("保存失败."))
	}
	return c.JSON(http.StatusOK, nport)
}

/*
用于处理/dev/ttyS5上的BMC电源管理模块返回的数据
*/
//var dataline = make([]byte, 128)
var mu sync.Mutex

func uartByteReceived(portname string, dat []byte) {
	/*if dat[0] == 0x0a { //strings.HasSuffix(string(dataline), "\n") {
		//dataline = append(dataline, dat...)
		//fmt.Print(string(bytes.Trim(dataline, "\x00")))
		mu.Lock()
		//defer mu.Unlock()
		err := ws.WriteMessage(websocket.TextMessage, bytes.Trim(dataline, "\x00"))
		mu.Unlock() //解锁

		if err != nil {
			fmt.Println(err)
		}
		dataline = make([]byte, 128)
	} else {
		dataline = append(dataline, dat...)
	}
	//defer mu.Unlock()
	*/
	//	if ws != nil {
	mu.Lock()
	conn := ClientWS[portname]
	if conn != nil {
		//err := ws.WriteMessage(websocket.TextMessage, bytes.Trim(dat, "\x00"))
		err := conn.WriteMessage(websocket.BinaryMessage, dat)
		if err != nil {
			log.Error(err)
		}
	}
	//err := core.NC.Publish(portname, dat)
	mu.Unlock() //解锁

}
